package sv.gob.mh.dgii.common.io;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.StringTokenizer;
import sv.gob.mh.dgii.common.Utils;

public class CsvFileReader implements Iterable<String[]>, Iterator<String[]>, Closeable {

    public static final String DEFAULT_SEPARATOR = ",";
    public static final String DEFAULT_QUOTE_CHARACTER = "\"";
    /**
     * Holds the next element (to be peeked)
     */
    public String[] next = null;
    /**
     * Working object
     */
    protected String[] currentLine = null;
    protected BufferedReader bufferedReader;

    public CsvFileReader(File f) throws FileNotFoundException {
        bufferedReader = new BufferedReader(new FileReader(f));
    }

    public CsvFileReader(String fileName) throws FileNotFoundException {
        bufferedReader = new BufferedReader(new FileReader(fileName));
    }

    public CsvFileReader(InputStream is) {
        InputStreamReader isr = new InputStreamReader(is);
        bufferedReader = new BufferedReader(isr);
    }

    public String[] parseLine(String line) {
        StringTokenizer tokenizer = new StringTokenizer(line, DEFAULT_SEPARATOR);

        String str[] = new String[tokenizer.countTokens()];
        for (int i = 0; tokenizer.hasMoreTokens(); i++) {
            String element = tokenizer.nextToken();
            str[i] = element;
        }
        return str;
    }

    @Override
    public Iterator<String[]> iterator() {
        return this;
    }

    @Override
    public boolean hasNext() {
        next = readLine();
        return !Utils.isNullOrEmpty(next);
    }

    @Override
    public String[] next() {
        String[] current;

        /*
         * si se llamo has next la linea a leer se encuentra en la variable next
         * sino se lee la linea del buffer
         */
        if (Utils.isNullOrEmpty(next)) {
            current = readLine();
        } else {
            current = next;
            next = null;
        }

        currentLine = current;

        try {
            if (current == null) {
                close();
            }
        } catch (IOException e) {
            // This does not happen
            // If it does, nobody cares
        }
        return (current);
    }

    private String[] readLine() {
        String temp = null;
        try {
            temp = bufferedReader.readLine();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        if (Utils.isNullOrEmpty(temp)) {
            return null;
        }
        return parseLine(temp);
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException("Can't remove lines from a file with this class");
    }

    @Override
    public void close() throws IOException {
        bufferedReader.close();
    }
}